package com.welike.shibo.controller.api;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.gson.JsonObject;
import com.welike.shibo.controller.BaseController;
import com.welike.shibo.eneity.*;
import com.welike.shibo.enums.ResultEnum;
import com.welike.shibo.service.*;
import com.welike.shibo.utils.IpUtil;
import com.welike.shibo.utils.ResultUtils;
import com.welike.shibo.utils.Tools;
import com.welike.shibo.vo.page.CommentPageVo;
import com.welike.shibo.vo.page.FollowVideoPageVo;
import com.welike.shibo.vo.page.VideoPageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author fangyu
 * @version v1.0.0
 * @since 2019-08-20 20:11
 */

@Slf4j
@Api(value = "视频相关接口")
@RestController
@RequestMapping("/api/video")
public class ApiVideoController extends BaseController {

    @Resource
    private VideoService videoService;

    @Resource
    private UserService userService;

    @Resource
    private ZanService zanService;

    @Resource
    private MsgService msgService;

    @Resource
    private GoodsService goodsService;

    @Resource
    private ShopHttpService shopHttpService;


    @Resource
    private CommentsService commentsService;

    @ApiOperation(value = "获取首页视频", notes = "获取首页视频")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "page", value = "页码", required = false),
            @ApiImplicitParam(paramType = "query", name = "pageSize", value = "分页容量", required = false)})
    @GetMapping("/list/index")
    public JsonResult getIndexList(
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/list/index");
        // 加入session判断
        LoginUser user = (LoginUser) getUser4Session();
        String uid = null;
        if (user != null) {
            uid = user.getUid();
        }
//        uid = "59957169";
        // 用户为空返回所有的首页信息
//        List<VideoPageVo> result = videoService.queryIndexPage(page, pageSize, uid);
        IPage<VideoPageVo> iPage = videoService.selectIndexPage(page, pageSize, uid);
        List<VideoPageVo> result = videoService.queryFollowAndLikeState(page, pageSize, uid, iPage.getRecords());
        log.info("result ==> {}", result);
        map.put("indexList", result);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }

    // TODO 分类获取全部(all)、同城(city)、大V(vip)、 推荐(hot)视频
    // 不同的类型给一个频道 = channel
    @ApiOperation(value = "获取不同频道的视频列表", notes = "获取全部、同城、大V、 推荐的视频列表")
    @GetMapping("/list/channel")
    public JsonResult getChannelList(
            @RequestParam(value = "channelType", required = false, defaultValue = "all") String channelType,
            @RequestParam(value = "city", required = false, defaultValue = "") String city,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/list/channel");
        LoginUser user = (LoginUser) getUser4Session();
        String uid = null;
        if (user != null) {
            uid = user.getUid();
        }
        IPage<VideoPageVo> iPage;
        // 直接获取所有的视频
        if ("all".equals(channelType)) {
            iPage = videoService.getAllVideoPageVo(page, pageSize);
            map.put("channel", "全部");
            // 获取同城的视频
        } else if ("city".equals(channelType)) {
            iPage = videoService.getCityVideoPageVo(page, pageSize, city);
            map.put("channel", "同城");
            // 获取大V的视频
        } else if ("vip".equals(channelType)) {
            iPage = videoService.getVipVideoPageVo(page, pageSize);
            map.put("channel", "大V");
            // 获取推荐的视频
        } else if ("hot".equals(channelType)) {
            iPage = videoService.getHotVideoPageVo(page, pageSize);
            map.put("channel", "推荐");
            // 其他，报错
        } else {
            return ResultUtils.error(ResultEnum.PARAM_ERROR.getCode(), "请选择频道!", map);
        }
        // 处理关注点赞状态
        List<VideoPageVo> result = videoService.queryFollowAndLikeState(page, pageSize, uid, iPage.getRecords());
        log.info("result ==> {}", result);
        map.put("indexList", result);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }


    @ApiOperation(value = "获取关注的人视频列表", notes = "获取关注的人视频列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "page", value = "页码", required = false),
            @ApiImplicitParam(paramType = "query", name = "pageSize", value = "分页容量", required = false)})
    @GetMapping("/list/follow")
    public JsonResult getFollowList(
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/list/follow");
        LoginUser user = (LoginUser) getUser4Session();
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg(), map);
        }
        String uid = user.getUid();
        // 通过uid查询关注的人信息
        List<String> uidList = userService.queryFollowList(uid);
        log.info("uidList ==> {}", uidList);
        if (uidList.size() == 0) {
            map.put("indexList", new ArrayList<>());
            map.put("total", 0);
            map.put("page", page);
            map.put("pageSize", pageSize);
            return ResultUtils.success(map);
        }
        List<FollowVideoPageVo> followVideoList = videoService.getFollowVideoPageVoList(page, pageSize, uid, uidList);
        log.info("result ==> {}", followVideoList);
        map.put("indexList", followVideoList);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }


    @ApiOperation(value = "视频点赞", notes = "视频点赞和取消点赞")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "vid", value = "视频id", required = true)})
    @PostMapping("/zan")
    public JsonResult zan(
            @RequestParam(value = "vid") String vid
    ) {
        map.clear();
        map.put("path", "/api/video/zan");
        LoginUser user = (LoginUser) getUser4Session();
        log.info("zanVideo: loginUser ==> {}", user);
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg(), map);
        }
        // 判断视频id是否为空
        if (Tools.isNull(vid)) {
            return ResultUtils.error(404, "请输入视频id");
        }

        // 查询vid视频被赞了多少次
        Video video = new Video();
        video.setId(vid);
        // 查询并返会结果, true 是成功点赞
        if (zanService.zanOrCancelZan(1, user.getUid(), vid)) {
            // 更新视频赞次数数据 => 从数据库查询
            Integer count = zanService.countByZanObjId(vid);
            video.setLikeCounts(count);
            map.put("likeCounts", count);
            map.put("likeStatus", true);
            // update 已修复
            videoService.updateById(video);
            log.info("zan success ==> {}", map);
            // 视频点赞推送
            String push_uid = videoService.queryUserIdById(vid);
            String desc = videoService.queryDescByVid(vid);
            String title = user.getNickname() + "点赞了你的\"" + desc + "\"作品";
            JsonObject json = new JsonObject();
            json.addProperty("favorStatus", true);
            json.addProperty("favorCount", count);
            json.addProperty("videoId", vid);
            boolean push_result = msgService.pushMsg(1, push_uid, title, null, json);
            if (push_result){
                Msg msg = new Msg();
                msg.setUserId(push_uid);
                msg.setCreateTime(new Date());
                msg.setMsgTitle(title);
                msg.setMsgContent("");
                msg.setMsgType(1);
                msgService.save(msg);
            }
            return ResultUtils.success("已点赞!", map);
        }
        // 更新视频赞次数数据 => 从数据库查询
        Integer count = zanService.countByZanObjId(vid);
        video.setLikeCounts(count);
        log.debug("count ==> {}", count);
        log.debug("video obj ==> {}", video);
        map.put("likeCounts", count);
        map.put("likeStatus", false);
        log.info("cancel zan success ==> {}", map);
        videoService.updateById(video);
        return ResultUtils.success("已取消点赞!", map);
    }

    @ApiOperation(value = "获取视频全部评论", notes = "获取当前视频的全部评论列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "vid", value = "视频id", required = true)})
    @GetMapping("/list/all_comment")
    public JsonResult getCommentList4Android(
            @RequestParam(value = "vid") String vid
    ) {
        map.clear();
        map.put("path", "/api/video/list/all_comment");
        if (Tools.isNull(vid)) {
            return ResultUtils.error(404, "请输入视频id");
        }
        String uid = null;
        LoginUser user = (LoginUser) getUser4Session();
        if (user != null) {
            uid = user.getUid();
        }
        List<CommentPageVo> commentPageVoList = commentsService.getCommentPageVoList(vid, uid);
        log.info("size => {}", commentPageVoList.size());
        map.put("commentList", commentPageVoList);
        return ResultUtils.success(map);
    }

    // TODO
    @ApiOperation(value = "获取视频评论", notes = "获取当前视频的评论列表")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "vid", value = "视频id", required = true),
            @ApiImplicitParam(paramType = "query", name = "page", value = "页码", required = false),
            @ApiImplicitParam(paramType = "query", name = "pageSize", value = "分页容量", required = false)})
    @GetMapping("/list/comment")
    public JsonResult getCommentList(
            @RequestParam(value = "vid") String vid,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/list/comment");
        if (Tools.isNull(vid)) {
            return ResultUtils.error(404, "请输入视频id");
        }
        String uid = null;
        LoginUser user = (LoginUser) getUser4Session();
        if (user != null) {
            uid = user.getUid();
        }
        List<CommentPageVo> commentPageVoList = commentsService.getCommentPageVoList(page, pageSize, vid, uid);
        map.put("commentList", commentPageVoList);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }

    @ApiOperation(value = "分享视频", notes = "用户分享视频")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "vid", value = "视频id", required = true)})
    @PostMapping("/share")
    public JsonResult shareVideo(
            @RequestParam(value = "vid") String vid
    ) {
        map.clear();
        map.put("path", "/api/video/share");
        LoginUser user = (LoginUser) getUser4Session();
        log.info("shareVideo: loginUser ==> {}", user);
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg());
        }
        if (Tools.isNull(vid)) {
            return ResultUtils.error(404, "请输入视频id");
        }
        Integer share_counts = videoService.queryShareCountsById(vid);
        Video video = new Video();
        video.setId(vid);
        share_counts += 1;
        video.setShareCounts(share_counts);
        videoService.updateById(video);
        map.put("shareCounts", share_counts);
        return ResultUtils.success("已成功分享!", map);
    }

    /**
     * @param file     文件流
     * @param desc     视频简介
     * @param audioId  音频id
     * @param duration 时长
     * @param width    视频宽
     * @param height   视频高
     * @param cover    视频封面
     * @param path     定位
     * @return JsonResult
     * @throws IOException 文件io异常
     */
    @ApiOperation(value = "发布视频", notes = "用户上传并发布视频")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "uploadFile", value = "视频文件", required = true),
            @ApiImplicitParam(paramType = "query", name = "videoDesc", value = "视频简介", required = true),
            @ApiImplicitParam(paramType = "query", name = "audioId", value = "使用音频id", required = true),
            @ApiImplicitParam(paramType = "query", name = "videoDuration", value = "视频时长", required = true),
            @ApiImplicitParam(paramType = "query", name = "videoWidth", value = "视频宽", required = true),
            @ApiImplicitParam(paramType = "query", name = "videoHeight", value = "视频高", required = true),
            @ApiImplicitParam(paramType = "query", name = "coverFile", value = "视频封面", required = true),
            @ApiImplicitParam(paramType = "query", name = "location", value = "定位", required = true),
            @ApiImplicitParam(paramType = "query", name = "shopId", value = "商品id", required = true),
    })
    @PostMapping("/publish")
    public JsonResult publish(
            @RequestParam(value = "uploadFile") MultipartFile file,
            @RequestParam(value = "videoDesc") String desc,
            @RequestParam(value = "audioId", defaultValue = "0") String audioId,
            @RequestParam(value = "videoDuration") Integer duration,
            @RequestParam(value = "videoWidth", defaultValue = "720") Integer width,
            @RequestParam(value = "videoHeight", defaultValue = "1280") Integer height,
            @RequestParam(value = "coverFile") MultipartFile cover,
            @RequestParam(value = "location") String path,
            @RequestParam(value = "shopId") String shopId,
            HttpServletRequest request
    ) throws IOException {
        map.clear();
        map.put("path", "/api/user/publish");
        LoginUser user = (LoginUser) getUser4Session();
        log.info("publish video: loginUser ==> {}", user);
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg(), map);
        }
        if (Tools.isNull(shopId)){
            shopId = null;
        }
        if (Tools.isNull(desc)){
            desc = null;
        } else if (desc.length() > 55){
            return ResultUtils.error("视频描述超过限定字数，请重新编辑提交");
        }
        if (Tools.isNull(audioId)){
            audioId = "0";
        }
        if (Tools.isNull(path)){
            path = IpUtil.getIpCity(request);
        }
            // shopId 不为空才判断
        if (!Tools.isNull(shopId)) {
            // 先查数据库是否有此商品， 没有则去查询
            if (goodsService.queryNameByShopId(shopId) == null){
                // 通过第三方接口查询商品详情
                Goods goods = shopHttpService.getGoodsInfoById(shopId);
                if (goods != null) {
                    goodsService.save(goods);
                } else {
                    return ResultUtils.error(ResultEnum.GOODS_NOT_EXIST.getCode(), ResultEnum.GOODS_NOT_EXIST.getMsg(), map);
                }
            }
        }
        log.info("file ==> {}", file);
        log.info("cover ==> {}", cover);
        log.info("shopId ==> {}", shopId);
        String videoUrl = videoService.uploadFile(file);
        log.info("videoUrl ==> {}", videoUrl);
        String coverUrl = videoService.uploadFile(cover);
        log.info("coverUrl ==> {}", coverUrl);
        String id = Tools.getUniqueKey();
        Video video = new Video(id, user.getUid(), audioId, path, desc, duration, width, height, coverUrl, videoUrl, shopId);
        videoService.save(video);
        map.put("videoInfo", video);
        return ResultUtils.success("成功上传", map);
    }

    @ApiOperation(value = "查询用户发布的视频", notes = "查询某一用户发布的视频")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "uid", value = "指定用户id", required = true)})
    @GetMapping("/list/user_publish")
    public JsonResult getUserPublishList(
            // 查询的uid
            @RequestParam(value = "uid") String uid,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/list/user_publish");
        LoginUser user = (LoginUser) getUser4Session();
        String login_uid = null;    // 登录账号的uid
        if (user != null) {
            login_uid = user.getUid();
        }

        // 通过uid查询关注的人信息
        List<VideoPageVo> result = videoService.selectUserPage(page, pageSize, uid, login_uid);
        map.put("indexList", result);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }


    @ApiOperation(value = "搜索视频", notes = "用户根据关键词搜索视频")
    @GetMapping("/search")
    public JsonResult search(
            @RequestParam(value = "key", required = false) String key,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page,
            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ) {
        map.clear();
        map.put("path", "/api/video/search");
        List<FollowVideoPageVo> result = videoService.searchVideo(page, pageSize, key);
        map.put("indexList", result);
        map.put("page", page);
        map.put("pageSize", pageSize);
        return ResultUtils.success(map);
    }

    /**
     * 删除视频
     *
     * @return JsonResult
     */
    @PostMapping(value = "/delete/{id}")
    @ResponseBody
    public JsonResult delVideo(
            @PathVariable(name = "id") String id
    ) {
        log.info("delVideo ==> {}", id);
        LoginUser user = (LoginUser) getUser4Session();
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg(), map);
        }
        return videoService.removeVideo(id);
    }

    /**
     * 合成
     * @param file 文件
     * @param desc 简介
     * @param audioId 音乐id
     * @param duration 时长
     * @param width 宽度
     * @param height 高度
     * @param cover 视频封面
     * @param path 定位
     * @param shopId 商品id
     * @param request 请求
     * @return JsonResult
     * @throws IOException
     */
    @PostMapping("/compound")
    public JsonResult compound(
            @RequestParam(value = "video") MultipartFile file,
            @RequestParam(value = "desc") String desc,
            @RequestParam(value = "audioId", defaultValue = "0") String audioId,
            @RequestParam(value = "duration") Integer duration,
            @RequestParam(value = "width", defaultValue = "720") Integer width,
            @RequestParam(value = "height", defaultValue = "1280") Integer height,
            @RequestParam(value = "cover") MultipartFile cover,
            @RequestParam(value = "location") String path,
            @RequestParam(value = "shopId") String shopId,
            HttpServletRequest request
    ) throws IOException {
        LoginUser user = (LoginUser) getUser4Session();
        map.clear();
        map.put("path", "/api/video/compound");
        if (user == null) {
            return ResultUtils.error(ResultEnum.NOT_LOGIN.getCode(), ResultEnum.NOT_LOGIN.getMsg(), map);
        }
        if (Tools.isNull(shopId)){
            shopId = null;
        }
        if (Tools.isNull(path)){
            path = IpUtil.getIpCity(request);
        }
        if (Tools.isNull(desc)){
            desc = null;
        }
        if (duration == null){
            return ResultUtils.error("视频时长不可为空");
        }
        // shopId 不为空才判断
        if (!Tools.isNull(shopId)) {
            // 先查数据库是否有此商品， 没有则去查询
            if (goodsService.queryNameByShopId(shopId) == null){
                // 通过第三方接口查询商品详情
                Goods goods = shopHttpService.getGoodsInfoById(shopId);
                if (goods != null) {
                    goodsService.save(goods);
                } else {
                    return ResultUtils.error(ResultEnum.GOODS_NOT_EXIST.getCode(), ResultEnum.GOODS_NOT_EXIST.getMsg(), map);
                }
            }
        }
        // 合成逻辑
        String videoUrl = videoService.compound(file, audioId, duration);
        // 上传视频封面
        String coverUrl = videoService.uploadFile(cover);
        log.info("videoUrl ==> {}", videoUrl);
        log.info("coverUrl ==> {}", coverUrl);
        String id = Tools.getUniqueKey();
        Video video = new Video(id, user.getUid(), audioId, path, desc, duration/1000, width, height, coverUrl, videoUrl, shopId);
//        Video video = new Video(id, "58656517", audioId, path, desc, duration, width, height, coverUrl, videoUrl, shopId);
        videoService.save(video);
        map.put("videoInfo", video);
        return ResultUtils.success("成功上传", map);
    }
}